/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package systole.math;

import java.math.BigDecimal;
import systole.domain.signals.FinalSignal;
import systole.domain.signals.Segment;

/**
 *
 * @author user
 */
public class SimpleDerivative implements Derivative {

    /*  public Segment derivate(Segment f){
    int nPoints = f.size();
    double h = 1.0;  //h interval taken
    double diff = 0;

    Segment derivated = new Segment(nPoints);

    for (int j=1; j < (nPoints -1); j++){
    //f'(x) = f(x+h) - f(x-h)/h ; En este caso, h = 1
    diff = (f.elementAt(j+1).doubleValue() - f.elementAt(j).doubleValue()) / (2*h);
    derivated.add(Double.valueOf(diff));
    }
    //continuo el mismo punto para no dejarlo en cero y que las restas sean enormes
    derivated.insertElementAt(derivated.elementAt(1), 0);
    derivated.insertElementAt(derivated.elementAt(nPoints - 2), nPoints-1);

    return derivated;
    }*/
    public FinalSignal derivate(Segment segment) {

        FinalSignal signal = new FinalSignal();

        signal.setFinalSegment(segment);

        Segment first = this.getFirstDerivative(segment);
        first.multiplyVectorBy(new BigDecimal(8));
        first.addValuteToVector(new BigDecimal(50.0));
        signal.setFirstDerivatite(first);

        Segment second = this.getSecondDerivative(first);
        second.multiplyVectorBy(new BigDecimal(10));
        second.addValuteToVector(new BigDecimal(50.0));
        signal.setSecondDerivative(second);

        Segment third = this.getThirdDerivative(second);
        third.multiplyVectorBy(new BigDecimal(2));
        third.addValuteToVector(new BigDecimal(50.0));
        signal.setThirdDerivative(third);


        Segment fourth = this.getThirdDerivative(third);
        fourth.multiplyVectorBy(new BigDecimal(5));
        fourth.addValuteToVector(new BigDecimal(50.0));
        signal.setFourthDerivative(fourth);

        return signal;
    }

    public Segment getFirstDerivative(Segment originalSegment) {
        return this.derivateiveByDifferences(originalSegment);
    }

    public Segment getSecondDerivative(Segment firstDerivative) {
        return this.derivateiveByDifferences(firstDerivative);
    }

    public Segment getThirdDerivative(Segment firstDerivative) {
        return this.derivateiveByDifferences(firstDerivative);
    }

    public Segment getFourthDerivative(Segment firstDerivative) {
        return this.derivateiveByDifferences(firstDerivative);
    }

    private Segment derivateiveByDifferences(Segment segment) {

        int nPoints = segment.size();
        BigDecimal h = BigDecimal.ONE;  //h interval taken
        BigDecimal diff = BigDecimal.ZERO;

        Segment derivated = new Segment(nPoints);

        for (int j = 1; j < (nPoints - 1); j++) {
            //f'(x) = f(x+h) - f(x-h)/h ; En este caso, h = 1
            diff = (segment.elementAt(j + 1).subtract(segment.elementAt(j - 1))).divide((h.multiply(new BigDecimal(2))),MathUtils.CONTEXT);
            // diff = (segment.elementAt(j).doubleValue() - segment.elementAt(j-1).doubleValue());
            derivated.add(diff);
        }
        //continuo el mismo punto para no dejarlo en cero y que las restas sean enormes
        derivated.insertElementAt(derivated.elementAt(1), 0);
        //derivated.insertElementAt(derivated.elementAt(nPoints - 2), nPoints - 1);

        return derivated;
    }
}
